In [1]:
import ipynb.fs.full.features as features
In [2]:
from sklearn import preprocessing
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sb
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin_min

%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')

df_train = pd.read_csv('./data/train.csv')
df_aux_train = df_train

df_test = pd.read_csv('./data/test.csv')
df_aux_test = df_train
In [3]:
# Normalizacion

def _normalizacion(df, columnas):
    x = df.values #returns a numpy array
    min_max_scaler = preprocessing.MinMaxScaler()
    x_scaled = min_max_scaler.fit_transform(x)
    df = pd.DataFrame(x_scaled)
    df.columns = columnas
    return df
In [4]:
def generar_grafico(df_completo, columnas, df_y=[]):
    """ df_completo: El df a calcular kmeans
        columnas: Es con que columnas se va a calcular
        df_y es la columna precio (es una serie)"""
    """Muestra el grafico de variacion entre 0 y 20 clusters(k)"""
    """Retorna X e y, para usar en el entrenamiento y la clasificacion"""
    df = df_completo[columnas].copy()
    for columna in columnas:
        df[columna] = df[columna].fillna(df[columna].mean())
    df = _normalizacion(df, columnas)
    
    X = np.array(df[columnas])
    y = None if type(df_y) == list else np.array(df_y)
    
    Nc = range(1, 20)
    kmeans = [KMeans(n_clusters=i) for i in Nc]
    score = [kmeans[i].fit(X).score(X) for i in range(len(kmeans))]

    plt.figure(figsize=(15,15))
    plt.plot(Nc,score)
    plt.xlabel('Number of Clusters')
    plt.ylabel('Score')
    plt.title('Elbow Curve')
    plt.show()
    
    return df, X, y
In [5]:
def etiquetado(k_cluster, X):
    # k Max es el largo de este arreglo
    colores=['red','green','blue','cyan','yellow', 'black', 'brown', 'orange', 'pink', 'purple', 'beige']
    kmeans = KMeans(n_clusters=k_cluster).fit(X)
    colores = colores[:k_cluster]
    # Clasificacion
    labels = kmeans.predict(X)
    C = kmeans.cluster_centers_ # Centroides
    asignar = []
    for row in labels:
        asignar.append(colores[row])
    # Grafico de todos los puntos clasificados:    
    if X.shape[1] > 2:
        fig = plt.figure(figsize=(20,20))
        ax = Axes3D(fig)
        ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=asignar,s=60)
        ax.scatter(C[:, 0], C[:, 1], C[:, 2], marker='*', c=colores, s=1000)
    return labels, asignar, X, C, colores
In [6]:
def proyeccion_2d(df, col1, col2, asignar, C, colores, fig_size=(20, 20)):
    f1 = df[col1].values
    f2 = df[col2].values

    plt.figure(figsize=fig_size)
    plt.scatter(f1, f2, c=asignar, s=70)
    plt.scatter(C[:, 0], C[:, 1], marker='*', c=colores, s=1000)
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.show()
In [7]:
def generar_csv_final(ids_series, labels, colores):
    final =  pd.DataFrame()
    # final['id'] = df_aux['id'].values
    final['id'] = ids_series.values
    final['label'] = labels;
    cantidadGrupo =  pd.DataFrame()
    cantidadGrupo['color'] = colores
    cantidadGrupo['cantidad'] = final.groupby('label').size()
    display(cantidadGrupo)
    return final

Features Básicos

Con el set de entrenamiento

In [8]:
columnas_basicas = ['metroscubiertos', 'metrostotales', 'antiguedad', 'habitaciones', 'garages', 'banos',
            'lat', 'lng', 'escuelascercanas', 'centroscomercialescercanos']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_basicas, df_precio)
In [9]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [10]:
proyeccion_2d(df_train, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [11]:
proyeccion_2d(df_train, 'antiguedad', 'metrostotales', asignar, C, colores)
In [12]:
ids_series = df_aux_train['id']
final_train_columnas_basicas = generar_csv_final(ids_series, labels, colores)
final_train_columnas_basicas = final_train_columnas_basicas.rename(columns={'label':'kmeans_basicos'})
color cantidad
0 red 18679
1 green 52076
2 blue 52382
3 cyan 35533
4 yellow 7253
5 black 74077

Con el set de testeo

In [13]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_basicas)
In [14]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [15]:
proyeccion_2d(df_test, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [16]:
proyeccion_2d(df_test, 'antiguedad', 'metrostotales', asignar, C, colores)
In [17]:
ids_series = df_aux_test['id']
final_test_columnas_basicas = generar_csv_final(ids_series, labels, colores)
final_test_columnas_basicas = final_test_columnas_basicas.rename(columns={'label':'kmeans_basicos'})
color cantidad
0 red 52373
1 green 74032
2 blue 52121
3 cyan 18679
4 yellow 7253
5 black 35542

Features Dependientes de la superficie

Set de entrenamiento

In [18]:
columnas_superficie = ['metroscubiertos', 'metrostotales']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_superficie, df_precio)
In [19]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [20]:
proyeccion_2d(df_train, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [21]:
ids_series = df_aux_train['id']
final_train_columnas_superficie = generar_csv_final(ids_series, labels, colores)
final_train_columnas_superficie = final_train_columnas_superficie.rename(columns={'label':'kmeans_superficie'})
color cantidad
0 red 47314
1 green 30618
2 blue 15989
3 cyan 14803
4 yellow 34566
5 black 18104
6 brown 42027
7 orange 36579

Set de testeo

In [22]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_superficie)
In [23]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [24]:
proyeccion_2d(df_test, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [25]:
ids_series = df_aux_test['id']
final_test_columnas_superficie = generar_csv_final(ids_series, labels, colores)
final_test_columnas_superficie = final_test_columnas_superficie.rename(columns={'label':'kmeans_superficie'})
color cantidad
0 red 36532
1 green 14949
2 blue 39422
3 cyan 16098
4 yellow 48862
5 black 34437
6 brown 17884
7 orange 31816

Features por metros totales cubiertos

Set de Entrenamiento

In [26]:
def metros_totales_cubiertos(df):
    punto20 = df_train['metrostotales'].quantile(0.2)
    punto40 = df_train['metrostotales'].quantile(0.4)
    punto60 = df_train['metrostotales'].quantile(0.6)
    punto80 = df_train['metrostotales'].quantile(0.8)
    punto20_cubiertos = df_train['metroscubiertos'].quantile(0.2)
    punto40_cubiertos = df_train['metroscubiertos'].quantile(0.4)
    punto60_cubiertos = df_train['metroscubiertos'].quantile(0.6)
    punto80_cubiertos = df_train['metroscubiertos'].quantile(0.8)
    df['metrostotales'] = df['metrostotales'].fillna(df['metroscubiertos'])
    df['metroscubiertos'] = df['metroscubiertos'].fillna(df['metrostotales'])
    df['metrostotales_log'] = np.log(df['metrostotales'])
    df['metroscubiertos_log'] = np.log(df['metroscubiertos'])
    df['porcentaje_metros'] = df['metroscubiertos']/df['metrostotales']
    df['diferencia_metros'] = df['metrostotales'] - df['metroscubiertos']
    df['intervalo_metros_totales'] = features.map_values(df['metrostotales'].values, lambda x: 1 if x<punto20 else (2 if punto20<x<punto40 else (3 if punto40<x<punto60 else(4 if punto60<x<punto80 else 5))))
    df['intervalo_metros_cubiertos'] = features.map_values(df['metroscubiertos'].values, lambda x: 1 if x<punto20_cubiertos else (2 if punto20_cubiertos<x<punto40_cubiertos else (3 if punto40_cubiertos<x<punto60_cubiertos else(4 if punto60_cubiertos<x<punto80_cubiertos else 5))))
    df['metroscubiertos_bins_unif'] = features.generar_intervalos_unif(df, 10, 'metroscubiertos')
    df['metroscubiertos_bins_perc'] = features.generar_intervalos_perc(df, 10, 'metroscubiertos')
    df['metroscubiertos_bins_unif'] = df['metroscubiertos_bins_unif'].astype(int)
    df['metroscubiertos_bins_perc'] = df['metroscubiertos_bins_perc'].astype(int)
    return df
In [27]:
df = df_aux_train.copy()
df = metros_totales_cubiertos(df)

columnas_metros_totales_cubiertos = ['metrostotales', 'metroscubiertos', 'metrostotales_log',
                    'metroscubiertos_log', 'porcentaje_metros', 'diferencia_metros', 'intervalo_metros_totales', 
                    'intervalo_metros_cubiertos', 'metroscubiertos_bins_unif', 'metroscubiertos_bins_perc' ]

df_precio = df['precio']
df_train, X, Y = generar_grafico(df, columnas_metros_totales_cubiertos, df_precio)
In [28]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [29]:
proyeccion_2d(df_train, 'intervalo_metros_cubiertos', 'diferencia_metros', asignar, C, colores)
In [30]:
ids_series = df['id']
final_train_columnas_metros_cubiertos = generar_csv_final(ids_series, labels, colores)
final_train_columnas_metros_cubiertos = final_train_columnas_metros_cubiertos.rename(columns={'label':'kmeans_metroscubiertos'})
color cantidad
0 red 41926
1 green 57292
2 blue 53898
3 cyan 28329
4 yellow 47199
5 black 11356

Set de testeo

In [31]:
df = df_aux_test.copy()
df = metros_totales_cubiertos(df)

columnas_metros_totales_cubiertos = ['metrostotales', 'metroscubiertos', 'metrostotales_log',
                    'metroscubiertos_log', 'porcentaje_metros', 'diferencia_metros', 'intervalo_metros_totales', 
                    'intervalo_metros_cubiertos', 'metroscubiertos_bins_unif', 'metroscubiertos_bins_perc' ]

df_test, X, Y = generar_grafico(df, columnas_metros_totales_cubiertos)
In [32]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [33]:
proyeccion_2d(df_test, 'intervalo_metros_cubiertos', 'diferencia_metros', asignar, C, colores)
In [34]:
ids_series = df['id']
final_test_columnas_metros_cubiertos = generar_csv_final(ids_series, labels, colores)
final_test_columnas_metros_cubiertos = final_test_columnas_metros_cubiertos.rename(columns={'label':'kmeans_metroscubiertos'})
color cantidad
0 red 57224
1 green 27674
2 blue 61032
3 cyan 10867
4 yellow 43642
5 black 39561

Por fecha

Para el set de entrenamiento

In [35]:
def generar_features_fecha(df):
    df['fecha'] = pd.to_datetime(df['fecha'])
    df['anio'] = df['fecha'].dt.year
    df['mes'] = df['fecha'].dt.month
    df['dia'] = df['fecha'].dt.day
    df['trimestre'] = (df['fecha'].dt.month)%3+1
    df['delta_desde_datos'] = (df['fecha'] - df['fecha'].min())
    df['dias_desde_datos'] = df['delta_desde_datos'].dt.days
    df['meses_desde_datos'] = df['dias_desde_datos'] // 30   # Mas o menos...
    df.pop('delta_desde_datos')
    df['fecha'] = df['fecha'].astype(int)
    return df
In [36]:
df = df_aux_train.copy()
df = generar_features_fecha(df)

columnas_por_fecha = ['fecha', 'anio', 'mes', 'dia', 'trimestre', 'dias_desde_datos', 'meses_desde_datos' ]

df_precio = df['precio']
df_train, X, Y = generar_grafico(df, columnas_por_fecha, df_precio)
In [37]:
labels, asignar, X, C, colores = etiquetado(11, X)
In [38]:
proyeccion_2d(df_train, 'dias_desde_datos', 'meses_desde_datos', asignar, C, colores)
In [39]:
ids_series = df['id']
final_train_columnas_fechas = generar_csv_final(ids_series, labels, colores)
final_train_columnas_fechas = final_train_columnas_fechas.rename(columns={'label':'kmeans_fechas'})
color cantidad
0 red 24451
1 green 22052
2 blue 18521
3 cyan 20091
4 yellow 20908
5 black 22955
6 brown 30891
7 orange 13375
8 pink 18733
9 purple 21135
10 beige 26888

Para el set de testeo

In [40]:
df = df_aux_test.copy()
df = generar_features_fecha(df)

df_test, X, Y = generar_grafico(df, columnas_por_fecha)
In [41]:
labels, asignar, X, C, colores = etiquetado(11, X)
In [42]:
proyeccion_2d(df_test, 'dias_desde_datos', 'meses_desde_datos', asignar, C, colores)
In [43]:
ids_series = df['id']
final_test_columnas_fechas = generar_csv_final(ids_series, labels, colores)
final_test_columnas_fechas = final_test_columnas_fechas.rename(columns={'label':'kmeans_fechas'})
color cantidad
0 red 23823
1 green 20822
2 blue 24438
3 cyan 20398
4 yellow 16386
5 black 22228
6 brown 16966
7 orange 22231
8 pink 27130
9 purple 21597
10 beige 23981

Features Por latitud y longitud

Set de entrenamiento

In [44]:
columnas_lat_lng = ['lat', 'lng']

df_precio = df['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_lat_lng, df_precio)
In [45]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [46]:
proyeccion_2d(df_train, 'lat', 'lng', asignar, C, colores)
In [47]:
ids_series = df_aux_train['id']
final_train_columnas_latlng = generar_csv_final(ids_series, labels, colores)
final_train_columnas_latlng = final_train_columnas_latlng.rename(columns={'label':'kmeans_latlng'})
color cantidad
0 red 137730
1 green 495
2 blue 3502
3 cyan 6256
4 yellow 104
5 black 10758
6 brown 64318
7 orange 16837

Para el set de test

In [48]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_lat_lng, df_precio)
In [49]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [50]:
proyeccion_2d(df_test, 'lat', 'lng', asignar, C, colores)
In [52]:
ids_series = df_aux_test['id']
final_test_columnas_latlng = generar_csv_final(ids_series, labels, colores)
final_test_columnas_latlng = final_test_columnas_latlng.rename(columns={'label':'kmeans_latlng'})
color cantidad
0 red 64314
1 green 104
2 blue 495
3 cyan 7707
4 yellow 6256
5 black 5818
6 brown 137394
7 orange 17912

Juntar todos los features en un solo df

Set de entrenamiento

In [53]:
clustering_train = pd.merge(final_train_columnas_basicas, final_train_columnas_superficie, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_metros_cubiertos, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_fechas, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_latlng, on='id')
clustering_train
# clustering_train.to_csv('./data/clustering_train_muchos.csv', index=False)
Out[53]:
id kmeans_basicos kmeans_superficie kmeans_metroscubiertos kmeans_fechas kmeans_latlng
0 254099 5 0 4 10 0
1 53461 3 1 0 2 6
2 247984 5 6 2 10 0
3 209067 2 0 4 2 6
4 185997 5 0 1 1 0
... ... ... ... ... ... ...
239995 119879 5 4 4 6 0
239996 259178 3 6 5 8 6
239997 131932 5 7 1 1 0
239998 146867 3 1 0 4 6
239999 121958 5 6 2 1 0

240000 rows × 6 columns

Set de Testeo

In [54]:
clustering_test = pd.merge(final_test_columnas_basicas, final_test_columnas_superficie, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_metros_cubiertos, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_fechas, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_latlng, on='id')
clustering_test
# clustering_test.to_csv('./data/clustering_test_muchos.csv', index=False)
Out[54]:
id kmeans_basicos kmeans_superficie kmeans_metroscubiertos kmeans_fechas kmeans_latlng
0 254099 1 4 2 6 6
1 53461 5 7 5 1 0
2 247984 1 2 0 0 6
3 209067 0 4 2 1 0
4 185997 1 4 2 5 6
... ... ... ... ... ... ...
239995 119879 1 5 2 4 6
239996 259178 5 2 3 8 0
239997 131932 1 0 0 5 6
239998 146867 5 7 4 7 0
239999 121958 1 2 0 5 6

240000 rows × 6 columns